package galaxy;

import java.util.Date;
import java.util.HashMap;
import java.util.Random;

import dviz.visualAnnotation.*;

@AttachVO("NodeObject")
public class Galaxy {
	HashMap<String, Planet> planets;
	static Random random = new Random(5);

	@ConstructMap("main")
	public Galaxy() {
		planets = new HashMap<String, Planet>();
	}

	public void generatePlanet(float minvel, float maxvel, float minmess,
			float maxmess, float space, int n) {
		for (int i = 0; i < n; i++) {
			float x = space * (random.nextFloat() - 0.5f);
			float y = space * (random.nextFloat() - 0.5f);
			float z = space * (random.nextFloat() - 0.5f);
			float vx = (maxvel - minvel) * random.nextFloat() + minvel;
			float vy = (maxvel - minvel) * random.nextFloat() + minvel;
			float vz = (maxvel - minvel) * random.nextFloat() + minvel;
			float mess = (maxmess - minmess) * random.nextFloat() + minmess;
			Planet p = new Planet();
			p.setName("Planet: " + i);
			p.setVx(vx);
			p.setVy(vy);
			p.setVz(vz);
			p.setX(x);
			p.setY(y);
			p.setZ(z);
			p.setMass(mess);
			p.setSize((float) Math.pow(mess, 1f / 3f));
			addPlanet(p);
		}
	}

	@FunctionMap("addNode")
	public void addPlanet(@Param("p") Planet p) {
		planets.put(p.getName(), p);
	}

	@FunctionMap("removeNode")
	public void removePlanet(@Param("p") Planet p) {
		planets.remove(p.getName());
	}

	final static float G = 20f;

	public void update(float spd) {
		for (Planet p1 : planets.values()) {
			float ax = 0, ay = 0, az = 0;
			for (Planet p2 : planets.values()) {
				if (p1 == p2)
					continue;
				float dx = (p2.getX() - p1.getX());
				float dy = (p2.getY() - p1.getY());
				float dz = (p2.getZ() - p1.getZ());
				float R2 = dx * dx + dy * dy + dz * dz;
				float len = (float) Math.sqrt(R2);
				if (Math.abs(R2) < 9500) {
					continue;
				}

				float g = p1.getMass() * p2.getMass() / R2 * G;
				ax += dx * g / len;
				ay += dy * g / len;
				az += dz * g / len;
			}
			// if(Float.isNaN(ax))
			// System.currentTimeMillis();
			p1.setVx(p1.getVx() + ax * spd);
			p1.setVy(p1.getVy() + ay * spd);
			p1.setVz(p1.getVz() + az * spd);
			p1.setX(p1.getX() + p1.getVx() * spd);
			p1.setY(p1.getY() + p1.getVy() * spd);
			p1.setZ(p1.getZ() + p1.getVz() * spd);

			// System.out.printf("%f %f %f\n",p1.getX(),p1.getY(),p1.getZ());
		}
	}

	public static void main(String s[]) throws Exception {
		Galaxy galaxy = new Galaxy();
		galaxy.generatePlanet(-150f, 150f, 1, 100, 50, 100);
		// galaxy.generatePlanet(-50, 50, 100, 100, 0, 1);
		Thread.sleep(2000);
		while (true) {
			galaxy.update(0.007f);
			Thread.sleep(10);
		}
	}
}
